package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.domain.StrategyTemplate;
import cn.wolfcode.luowowo.search.query.StatisVoQuery;
import cn.wolfcode.luowowo.search.repository.StrategyTemplateRepository;
import cn.wolfcode.luowowo.search.service.IStrategySearchService;
import cn.wolfcode.luowowo.search.vo.StatisVo;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategySearchServiceImpl implements IStrategySearchService {
    @Autowired
    private StrategyTemplateRepository repository;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Override
    public void saveOrUpdate(StrategyTemplate strategyTemplate) {
        repository.save( strategyTemplate );
    }

    @Override
    public List <Map <String, Object>> queryTemeCds() {
        List <StatisVo> statisVos = getCondinationGroub( "themeId", "themeName" );
        //遍历list,查询出来每个主题下面的攻略的目的的list
        List <Map <String, Object>> themes = new ArrayList <>();
        List <String> strings = new ArrayList <>();
        for (StatisVo statisVo : statisVos) {
            Map <String, Object> temp = new HashMap <>();
            List <Map> dests = new ArrayList <>();
            //根据主题的id,查询出来所有的StrategyTemplate集合
            List <StrategyTemplate> templates = repository.findByThemeId( statisVo.getId() );
//            TermQueryBuilder query = QueryBuilders.termQuery( "themeId", statisVo.getId() );
//            Iterable <StrategyTemplate> search = repository.search( query );
            for (StrategyTemplate st : templates) {
                if (strings.contains( st.getDestName() )) {
                    continue;
                }
                Map <String, Object> destmap = new HashMap <>();
                destmap.put( "id", st.getDestId() );
                destmap.put( "name", st.getDestName() );
                dests.add( destmap );
                strings.add( st.getDestName() );
            }
            temp.put( "theme", statisVo );
            temp.put( "dests", dests );
            themes.add( temp );
        }
        Collections.sort( themes, new Comparator <Map <String, Object>>() {
            @Override
            public int compare(Map <String, Object> o1, Map <String, Object> o2) {
                List <Map> dests1 = (List <Map>) o1.get( "dests" );
                List <Map> dests2 = (List <Map>) o2.get( "dests" );
                return dests2.size() - dests1.size();
            }
        } );

        //2.再查询目的地的时候去除重复
        //3.排序按照主题下面的数量来排序,将statis中的数据来排序

        return themes.size()>10? themes.subList( 0, 10 ):themes;
    }

        //根据条件来分组
    private List <StatisVo> getCondinationGroub(String type1, String type2) {
        //查询主题及其下面攻略的目的地
        //1.先根据主题的id分类,同时将主题的名字查询出来,多列查询
        List <CompositeValuesSourceBuilder <?>> sources = new ArrayList <>();
        //第一个条件是分组的名称,第二个条件是分组的类型,分组的类型相当于给分组条件起的别名,在后面获取的使用
        TermsValuesSourceBuilder field1 = new TermsValuesSourceBuilder( "id" ).field( type1 );
        TermsValuesSourceBuilder field2 = new TermsValuesSourceBuilder( "name" ).field( type2 );
        sources.add( field2 );
        sources.add( field1 );
        CompositeAggregationBuilder cbuilder = new CompositeAggregationBuilder( "StatisVoGroub", sources );
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.addAggregation( cbuilder );
        //分组为了只查询一条数据,设置分页的数组,不设置会将所有的数据查询出来
        //此处不需要设置排序,因为所要的数据是里面的内容,无法排序
        builder.withPageable( PageRequest.of( 0, 1 ) );
        if("countryId".equals( type1 )){
            builder.withQuery( QueryBuilders.boolQuery().mustNot( QueryBuilders.termQuery( "countryId",1 )) );
        }
        AggregatedPage <StrategyTemplate> page = (AggregatedPage) repository.search( builder.build() );
        InternalComposite themeGroub = (InternalComposite) page.getAggregations().get( "StatisVoGroub" );
        //用来查询出来所有的主题分类的 list
        List <StatisVo> statisVos = new ArrayList <>();
        StatisVo vo;
        for (CompositeAggregation.Bucket bucket : themeGroub.getBuckets()) {
            //根据设置的值,将查询条件拼接出来
            Long id = Long.parseLong( bucket.getKey().get( "id" ).toString() );
            String name = bucket.getKey().get( "name" ).toString();
            //分组的数量
            long count = bucket.getDocCount();
            vo = new StatisVo( id, name, count );
            //将这个值封装成对象,同时放入到list的集合中
            statisVos.add( vo );
        }


        Collections.sort( statisVos, new Comparator <StatisVo>() {
            @Override
            public int compare(StatisVo o1, StatisVo o2) {
                long i = o2.getCount() - o1.getCount();
                return (int)i;

            }
        } );

        return statisVos;
    }

    @Override
    public List <StatisVo> queryThemesGroubTop10() {
        List <StatisVo> statisVos = getCondinationGroub( "themeId", "themeName" );
        return statisVos;
    }

    @Override
    public List <StatisVo> queryChinasGroub() {
        //此时不是根据主题来分类,是根据省份来分类
        //将身份的id,名称和省份下攻略的数量查询出来
        //  TermsValuesSourceBuilder buider = new TermsValuesSourceBuilder( "name" ).field( "provinceId" );
        List <StatisVo> statisVos = getCondinationGroub( "provinceId", "provinceName" );
        return statisVos;
    }

    @Override
    public List <StatisVo> queryAbroadsGroub() {

        List <StatisVo> statisVos = getCondinationGroub( "countryId", "countryName" );
        return statisVos;
    }

    @Override
    public Page <StrategyTemplate> query(StatisVoQuery qo) {
        int type = qo.getType();
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withPageable(PageRequest.of( qo.getCurrentPage() - 1, qo.getPageSize() , Sort.Direction.DESC,qo.getOrderBy()) );
        if (type == StatisVoQuery.STATICQUERY_TYPE_THEMES) {
            //查询该分类下的所有的攻略
            builder.withQuery( QueryBuilders.termQuery( "themeId",qo.getTypeValue() ) );

            return  repository.search( builder.build() );
        } else if (type == StatisVoQuery.STATICQUERY_TYPE_ABROADS) {
            builder.withQuery( QueryBuilders.termQuery( "countryId",qo.getTypeValue() ) );
            return  repository.search( builder.build() );
        } else if (type == StatisVoQuery.STATICQUERY_TYPE_CHINAS) {

            builder.withQuery( QueryBuilders.termQuery( "provinceId",qo.getTypeValue() ) );
            return  repository.search( builder.build() );
        }

        return repository.search( builder.build() );
    }

    @Override
    public List <StrategyTemplate> queryByDestName(String destName) {

        List <StrategyTemplate> list=repository.findByDestName(destName);
            return list;
    }

}